<template>
  <el-container class="layout-container">
    <el-header :height="$cssVars.headerHeight">
      <logo />
      <operation-button
        @preview:form="e => $refs.previewForm.show(e, formConfig)"
        @preview:config="e => $refs.previewJson.show(e)"
        @save="saveFormConfig"
        @delete="clearEmpty"
      />
    </el-header>
    <el-container>
      <el-aside class="aside-left" :width="$cssVars.asideLeftWidth">
        <div v-for="row in basicComponents" :key="row.uid">
          <h3 class="basic-component-title">
            <svg-icon icon-class="component" />
            {{ row.title }}
          </h3>
          <ve-draggable
            class="basic-component"
            :list="row.list"
            draggable=".basic-component-item"
            :group="{name:'basicComponentGroup',pull:'clone'}"
            :sort="false"
            :clone="onClone"
            @end="onEnd"
          >
            <template v-for="item in row.list">
              <div v-if="item" :key="item.uid" class="basic-component-item">{{ item.name }}</div>
            </template>
          </ve-draggable>
        </div>
      </el-aside>
      <el-main class="v-drag-form">
        <ve-form-drag
          v-model="formData"
          :config="formConfig"
          :drag-config="getDragConfig"
          @copy="copyComponent"
          @remove="removeComponent"
          @select="selectComponent"
        />
      </el-main>
      <el-aside class="aside-right" :width="$cssVars.asideRightWidth">
        <el-tabs v-model="tabActiveName">
          <el-tab-pane label="组件属性" name="1">
            <component-attrs v-if="dragContext" :model="dragContext" @input="updateComponentProps" />
          </el-tab-pane>
          <el-tab-pane label="表单属性" name="2">
            <form-attrs :config="formConfig" @input="updateFormProps" />
          </el-tab-pane>
        </el-tabs>
      </el-aside>
    </el-container>

    <preview-json ref="previewJson" :config="formConfig" @input="updateFormConfig" />
    <preview-form ref="previewForm" :value="formConfig" />
  </el-container>
</template>

<script>
import VeDraggable from "vuedraggable";
import VeFormDrag from "@lib/draggable/formDrag";
import { componentDef, basicComponents } from "@lib/config/components";
import { objectFormat, localCache, getId, toJson } from "@/utils/tools";

import Logo from "./header/Logo";
import OperationButton from "./header/OperationButton";

import FormAttrs from "./components/FormAttrs";
import PreviewForm from "./components/PreviewForm";
import PreviewJson from "./components/PreviewJson";
import ComponentAttrs from "./components/ComponentAttrs";

const basicComponentDef = componentDef();
const CACHE_KEY = "app.formConfig";
let currComponent = null;

export default {
  name: "Home",
  components: {
    VeDraggable,
    VeFormDrag,
    Logo,
    OperationButton,
    PreviewForm,
    PreviewJson,
    ComponentAttrs,
    FormAttrs,
  },
  data() {
    return {
      basicComponents: basicComponents(),
      tabActiveName: "1",
      formData: {},
      formConfig: {
        formProps: {
          labelWidth: 80,
        },
        rules: {},
        elements: [],
      },
      dragContext: null,
    };
  },
  computed: {
    getDragConfig() {
      return {
        list: this.formConfig.elements,
        group: "basicComponentGroup",
        dragContext: this.dragContext,
      };
    },
  },
  watch: {
    "formConfig.elements": {
      deep: true,
      immediate: true,
      handler() {
        this.getFormFields();
        this.getFormRules();
      },
    },
  },
  mounted() {
    this.formConfig.elements = Object.keys(basicComponentDef).map((k) => {
      this.dragContext = this.handelComponent(basicComponentDef[k]);
      return this.dragContext;
    });
    console.log("formConfig.elements", objectFormat(this.formConfig.elements));

    // const o = this.handelComponent(basicComponentDef.radio)
    // this.formConfig.elements.push(o)
    // this.setDragContext(o)

    /* const o = toJson(localCache(CACHE_KEY))
    if (o && o.elements.length) {
      o.elements.forEach((row, i) => (row[i] = this.handelComponent(row)))
      this.formConfig = o
      this.setDragContext(o.elements[0])
    } else {
      const o = this.handelComponent(basicComponentDef.radio)
      this.formConfig.elements.push(o)
      this.setDragContext(o)
    } */
  },
  methods: {
    manageComponents(uid, type = 1, data) {
      let res = null;
      const fn = (list) =>
        list.some((o, i) => {
          if (!o) return false;
          res = o;
          // console.log('manageComponents', { 'o.uid': o.uid, uid })
          if (o.uid === uid) {
            if (type === 1) {
              // 查找
            } else if (type === 2) {
              // 添加
              o.subWidgets.push(data);
            } else if (type === 3) {
              // 替换
              list.splice(i, 1, data);
            } else if (type === 4) {
              // 删除
              list.splice(i, 1);
            }
            return true;
          }
          fn(o.subWidgets);
        });
      fn(this.formConfig.elements);
      return res;
    },
    selectComponent(uid) {
      this.setDragContext(this.manageComponents(uid));
    },
    copyComponent({ uid, isSubWidget }) {
      const data = this.handelComponent(this.manageComponents(uid));
      if (isSubWidget) {
        this.manageComponents(uid, 2, { ...data, isSubWidget: true });
      } else {
        this.formConfig.elements.push({ ...data, isSubWidget: false });
      }
    },
    removeComponent(uid) {
      this.manageComponents(uid, 4);
      if (!this.formConfig.elements.length) {
        this.setDragContext(null);
      } else if (this.dragContext.uid === uid) {
        this.setDragContext(this.formConfig.elements[0]);
      }
    },
    setDragContext(obj) {
      this.dragContext = obj;
    },
    handelComponent(obj) {
      const o = objectFormat(obj);
      o.uid = getId();
      return o;
    },
    onClone(obj) {
      currComponent = this.handelComponent(obj);
      return currComponent;
    },
    onEnd({ form, to }) {
      if (form === to) return;
      this.setDragContext(currComponent);
    },
    getFormFields() {
      const o = {};
      this.formConfig.elements.forEach(({ widget: { field, props } }) => {
        if (field && props) o[field] = props.defaultValue;
      });
      this.formData = o;
    },
    getFormRules() {
      const o = {};
      this.formConfig.elements.forEach(({ widget: { field, rules } }) => {
        if (field) o[field] = rules;
      });
      this.formConfig.rules = o;
    },
    updateFormProps(o) {
      this.formConfig.formProps = o;
    },
    updateComponentProps(o) {
      this.manageComponents(o.uid, 3, o);
      this.setDragContext(o);
    },
    updateFormConfig(obj) {
      this.formConfig = obj;
    },
    saveFormConfig() {
      localCache(CACHE_KEY, this.formConfig);
    },
    clearEmpty() {
      localCache(CACHE_KEY, "");
      this.formConfig.elements = [];
      this.setDragContext(null);
    },
  },
};
</script>
